/*
 * ClientListener.java
 *
 * Created on October 8, 2006, 1:23 AM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package net.sf.iSnake.server;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.net.SocketException;
import net.sf.iSnake.core.*;

/**
 * This class creates a thread for each socket connection in server side
 * and handels their corresponding Client.
 * @author Suraj
 */
public class ClientListener extends Thread{
    private int ClientNo;
    private Socket Soc;
    private ObjectInputStream ois=null;
    private ObjectOutputStream oos=null;
    private ServerCorePre ServerPre;
    private ServerCorePost ServerPost;
    private boolean stop=false;
    private ServerNetworkInterface ServerInterface=null;
    private Object obj=null;
    
    /**Creates a new instance of ClientListener
     */
    public ClientListener(){
    }
    /**Creates a new instance of ClientListener with arguments
     * @param ServerPre The Pre-session server
     * @param ServerPost The Post-session server
     * @param ClientNo The Client no
     * @param Soc This is a socket wiich this thread should handel
     */
    public ClientListener(ServerCorePre ServerPre,ServerCorePost ServerPost,int ClientNo,Socket Soc){
        this.ServerInterface=ServerInterface;
        this.ClientNo=ClientNo;
        this.Soc=Soc;
        try{
            Soc.setTcpNoDelay(true);
        } catch(SocketException e){}
        this.ServerPre=ServerPre;
        this.ServerPost=ServerPost;
        this.start();
        ServerPre.status(ServerStatus.DEBUG_INFO,"Listener Started for "+ClientNo);
    }
    public void run(){
        try {
            ois=new ObjectInputStream(Soc.getInputStream());
            oos=new ObjectOutputStream(Soc.getOutputStream());
            ServerPre.status(ServerStatus.DEBUG_INFO,"IO stream opened "+ClientNo);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        try {
            oos.writeInt(ClientNo);
            oos.flush();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        try {
            
            while((obj=ois.readObject())!=null && !isStop()){
                if(ServerPre.isPreMode()){
                    ServerPre.forwardPacket(ClientNo,obj);
                } else if(ServerPre.isPostMode()){
                    ServerPost.forwardPacket(ClientNo,obj);
                } else{
                    ServerPre.status(ServerStatus.DEBUG_INFO,"intermediate packet received... from "+ClientNo);
                    ServerPre.getSi().forwardSignal(ClientNo,obj);
                }
            }
        } catch (SocketException ex){
            if (ex.getMessage().equalsIgnoreCase("Connection reset")){
                ServerPre.status(ServerStatus.DEBUG_INFO,"Client left :: Client no: "+ClientNo);
                ServerPre.removeClient(ClientNo);
                if(ServerPre.isPostMode()){
                    postmodeISCPpacketForSend pmps=new postmodeISCPpacketForSend();
                    pmps.setPostmodeCommandSend(ISCP.POST_CMD_SEND_dxdy);
                    pmps.setPlayer_id(Short.parseShort(""+ClientNo));
                    pmps.setDxDy(Short.parseShort(""+-1),Short.parseShort(""+-1));
                    ServerPost.forwardPacket(ClientNo,pmps);
                } else if(!ServerPre.isPreMode()){
                    postmodeISCPpacketForSend pmps=new postmodeISCPpacketForSend();
                    pmps.setPostmodeCommandSend(ISCP.POST_CMD_SynchronizeClient);
                    ServerPre.getSi().forwardSignal(ClientNo,pmps);
                }
                setStop(true);
            } else
                ex.printStackTrace();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        try{Soc.close();} catch(IOException ex){}
    }
    /**
     *This method sends the object to the Client
     *@param obj Object to be send to the Client
     */
    public boolean send(Object obj){
        try{
            oos.writeObject(obj);
            oos.flush();
            oos.reset();
        } catch (Exception e){
            return (false);
        } finally{
            return (true);
        }
        
    }
    /**This method closes the thread
     */
    public void close(){
        setStop(true);
    }
    /**Returns wether this Thread is closed or not
     */
    public boolean isStop() {
        return stop;
    }
    /**Sets/Resets the stop variable,and so does this thread. But
     * remember setting true wont resume this thread
     */
    public void setStop(boolean stop) {
        this.stop = stop;
    }
}
